home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / machack / Hacks96 / FlyPaper.sit / Fly Paper / FlyPaper Source / App Sources / floaters.c < prev    next >
Text File  |  1996-06-22  |  10KB  |  315 lines

  1. // File "floaters.c" - 
  2.  
  3. #include <Windows.h>
  4. #include <GestaltEqu.h>
  5. #include <TextServices.h>
  6.  
  7. #include "floaters.h"
  8. #include "FlyPaperApp.h"
  9.  
  10. // * ****************************************************************************** *
  11. // Global Declarations
  12.  
  13. extern GlobalsRec glob;
  14.  
  15. // * ****************************************************************************** *
  16. // * ****************************************************************************** *
  17.  
  18. WindowPtr NewFloater(Ptr wStorage, Rect *bounds, Str255 title, Boolean visFlag,
  19.         short wdefProc, WindowPtr behind, Boolean closeFlag, long refCon, long hotApp,
  20.         FloaterEventProcPtr eventHandler, FloaterCloseProcPtr closeHandler) {
  21.     short err=0;
  22.     Boolean myStorage = (wStorage) ? true : false;
  23.     WindowPtr win=0;
  24.     FloaterQElemPtr myQElem;
  25.     
  26.     if (myStorage) wStorage = NewPtr(sizeof(WindowRecord));
  27.     if (myStorage && !wStorage) return(0);
  28.     
  29.     err = NewServiceWindow(wStorage, bounds, title, false, wdefProc, (WindowPtr) -1,
  30.             closeFlag, (ComponentInstance) kCurrentProcess, &win);
  31.     if (err) {
  32.         if (myStorage) DisposePtr(wStorage);
  33.         return(0);
  34.         }
  35.         
  36.     myQElem = (FloaterQElemPtr) NewPtrSys(sizeof(* myQElem));
  37.     if (! myQElem) {
  38.         if (win) CloseServiceWindow(win);
  39.         if (myStorage) DisposePtr(wStorage);
  40.         return(0);
  41.         }
  42.     myQElem->qLink = 0;
  43.     myQElem->qType = 0;
  44.     myQElem->hideMe = false;
  45.     myQElem->hotApplication = hotApp;
  46.     myQElem->floatWindow = win;
  47.     myQElem->eventHandler = eventHandler;
  48.     myQElem->closeHandler = closeHandler;
  49.     Enqueue((QElem *) myQElem, &glob.allFloatWindows);
  50.  
  51.     SetWRefCon(win, refCon);
  52.     HiliteWindow(win, -1);
  53.     if (visFlag) ShowHideFloater(win);
  54.  
  55.     return(win);
  56.     }
  57.  
  58. // * ****************************************************************************** *
  59. // * ****************************************************************************** *
  60.  
  61. void CloseFloater(WindowPtr win) {
  62.     FloaterQElemPtr myQElem, qTail;
  63.     
  64.     // Get the window's QElem and release its memory
  65.     myQElem = GetOneFloater(win, true);
  66.     if (myQElem) DisposePtr((Ptr) myQElem);
  67.     
  68.     ShowHide(win, 0);
  69.     CloseServiceWindow(win);
  70.  
  71.     UpdateFloater(0);
  72.     }
  73.  
  74. // * ****************************************************************************** *
  75. // * ****************************************************************************** *
  76.  
  77. void DisposeFloater(WindowPtr win) {
  78.     FloaterQElemPtr myQElem;
  79.     
  80.     // Get the window's QElem and release its memory
  81.     myQElem = GetOneFloater(win, true);
  82.     if (myQElem) DisposePtr((Ptr) myQElem);
  83.     
  84.     ShowHide(win, 0);
  85.     CloseServiceWindow(win);
  86.     DisposePtr((Ptr) win);
  87.     
  88.     UpdateFloater(0);
  89.     }
  90.  
  91. // * ****************************************************************************** *
  92. // * ****************************************************************************** *
  93.  
  94. FloaterQElemPtr GetOneFloater(WindowPtr win, Boolean dequeueIt) {
  95.     FloaterQElemPtr myQElem;
  96.     
  97.     // Get the window's QElem and release its memory
  98.     if (glob.allFloatWindows.qTail) glob.allFloatWindows.qTail->qLink = 0;
  99.     for(myQElem = (FloaterQElemPtr) glob.allFloatWindows.qHead; myQElem && 
  100.             (myQElem->floatWindow != win); myQElem = myQElem->qLink);
  101.  
  102.     if (dequeueIt && myQElem) Dequeue((QElem *) myQElem, &glob.allFloatWindows);
  103.     return(myQElem);
  104.     }
  105.  
  106. // * ****************************************************************************** *
  107. // * ****************************************************************************** *
  108.  
  109. FloaterQElemPtr GetIndFloater(short index, Boolean dequeueIt) {
  110.     FloaterQElemPtr myQElem;
  111.     
  112.     if (index <= 0) return(0);
  113.     
  114.     // Get the window's QElem and release its memory
  115.     if (glob.allFloatWindows.qTail) glob.allFloatWindows.qTail->qLink = 0;
  116.     for(myQElem = (FloaterQElemPtr) glob.allFloatWindows.qHead, index--;
  117.             myQElem && index; myQElem = myQElem->qLink, index--);
  118.  
  119.     if (dequeueIt && myQElem) Dequeue((QElem *) myQElem, &glob.allFloatWindows);
  120.     return(myQElem);
  121.     }
  122.  
  123. // * ****************************************************************************** *
  124. // * ****************************************************************************** *
  125.  
  126. // If you have set the Hot Application, then this function checks whether that
  127. //   process is the front one and hides or shows the window as appropriate.
  128. Boolean ShowHideFloater(WindowPtr win) {
  129.     Boolean toHide, anyChanges=false;
  130.     short index;
  131.     ProcessSerialNumber psn;
  132.     ProcessInfoRec pInfo;
  133.     FloaterQElemPtr myQElem;
  134.     
  135.     pInfo.processInfoLength = sizeof(pInfo);
  136.     pInfo.processName = 0;
  137.     pInfo.processAppSpec = 0;
  138.     
  139.     if (GetFrontProcess(&psn) || GetProcessInformation(&psn, &pInfo)) 
  140.         pInfo.processSignature = -1;
  141.  
  142.     if (! win) {
  143.         for(myQElem = GetIndFloater(index = 1, false); myQElem; 
  144.                 myQElem = GetIndFloater(++index, false)) {
  145.             win = myQElem->floatWindow;
  146.             if (! win) continue;
  147.  
  148.             toHide = glob.hideFloats || glob.blockFloats || glob.modalFloats || 
  149.                     myQElem->hideMe || (myQElem->hotApplication && 
  150.                     (pInfo.processSignature != myQElem->hotApplication));
  151.             
  152.             if (! toHide && ! ((WindowPeek) win)->visible) {
  153.                 ShowHide(win, true);
  154.                 anyChanges = true;
  155.                 }
  156.               else if (toHide && ((WindowPeek) win)->visible) {
  157.                 ShowHide(win, false);
  158.                 anyChanges = true;
  159.                 }
  160.             }
  161.         }
  162.       else if (myQElem = GetOneFloater(win, false)) {
  163.         toHide = glob.hideFloats || glob.blockFloats || glob.modalFloats || 
  164.                 myQElem->hideMe || (myQElem->hotApplication && 
  165.                 (pInfo.processSignature != myQElem->hotApplication));
  166.         
  167.         if (! toHide && ! ((WindowPeek) win)->visible) {
  168.             ShowHide(win, true);
  169.             anyChanges = true;
  170.             }
  171.           else if (toHide && ((WindowPeek) win)->visible) {
  172.             ShowHide(win, false);
  173.             anyChanges = true;
  174.             }
  175.         }
  176.     return(anyChanges);
  177.     }
  178.  
  179. // * ****************************************************************************** *
  180. // * ****************************************************************************** *
  181.  
  182. void UpdateFloater(WindowPtr win) {
  183.     short index;
  184.     EventRecord theEvent;
  185.     FloaterQElemPtr myQElem;
  186.  
  187.     theEvent.what = updateEvt;
  188.     theEvent.when = TickCount();
  189.     theEvent.message = (long) win;
  190.     
  191.     if (! win) {
  192.         // Call the event handler for every floating window
  193.         for(myQElem = GetIndFloater(index = 1, false); myQElem; 
  194.                 myQElem = GetIndFloater(++index, false)) {
  195.             win = myQElem->floatWindow;
  196.             if (win && ! EmptyRgn(((WindowPeek) win)->updateRgn)) {
  197.                 theEvent.message = (long) win;
  198.                 if (myQElem->eventHandler) (*myQElem->eventHandler)(&theEvent, win);
  199.                 }
  200.             }
  201.         }
  202.       else if (myQElem = GetOneFloater(win, false))
  203.         // Call the event handler for the indicated window
  204.         if (! EmptyRgn(((WindowPeek) win)->updateRgn))
  205.             if (myQElem->eventHandler) (*myQElem->eventHandler)(&theEvent, win);
  206.  
  207.     }
  208.  
  209. // * ****************************************************************************** *
  210. // * ****************************************************************************** *
  211.  
  212. void EventDispatchFloaters(EventRecord *theEvent, WindowPtr win) {
  213.     short index;
  214.     FloaterQElemPtr myQElem;
  215.  
  216.     if (! win) {
  217.         // Call the event handler for every floating window
  218.         for(myQElem = GetIndFloater(index = 1, false); myQElem; 
  219.                 myQElem = GetIndFloater(++index, false)) 
  220.             if (myQElem->eventHandler) 
  221.                 (*myQElem->eventHandler)(theEvent, myQElem->floatWindow);
  222.         }
  223.       else if (myQElem = GetOneFloater(win, false))
  224.         // Call the event handler for the indicated window
  225.         if (myQElem->eventHandler) 
  226.             (*myQElem->eventHandler)(theEvent, myQElem->floatWindow);
  227.  
  228.     }
  229.  
  230.  
  231. // * ****************************************************************************** *
  232. // * ****************************************************************************** *
  233.  
  234. void CloseRemainingFloaters() {
  235.     FloaterQElemPtr myQElem;
  236.  
  237.     // For each tracked window, we call its close procedure - WE'RE QUITTING
  238.     //   Of course, you may find it necessary to add a "Save?" dialog, and escape
  239.     //   the quit sequence on a user cancel -- this code would need to be fixed.
  240.     while(myQElem = GetIndFloater(1, false)) 
  241.         if (myQElem->closeHandler) (*myQElem->closeHandler)(myQElem->floatWindow);
  242.           else DisposeFloater(myQElem->floatWindow);
  243.     }
  244.  
  245. // * ****************************************************************************** *
  246. // * ****************************************************************************** *
  247.  
  248. Boolean GetFloaterEvent(EventRecord *theEvent) {
  249.     Boolean floaterEvent = false;
  250.     short err=0, index;
  251.     EvQEl *fwdEvent=0;
  252.     FloaterQElemPtr myQElem;
  253.     
  254.     // Extract any forwarded events... and treat them as normal
  255.     if (fwdEvent = (EvQEl *) glob.forwardedEvents.qHead)
  256.         err = Dequeue((QElemPtr) fwdEvent, &glob.forwardedEvents);
  257.  
  258.     if (fwdEvent && !err) {
  259.         BlockMove(&fwdEvent->evtQWhat, theEvent, sizeof(EventRecord));
  260.         DisposePtr((Ptr) fwdEvent);
  261.         
  262.         // DONT ZERO IT OUT - The pointer indicates that we are
  263.         //   handling an event for a Floater window. 
  264.  
  265.         floaterEvent = true;
  266.         }
  267.         
  268.     return(floaterEvent);
  269.     }
  270.  
  271. // * ****************************************************************************** *
  272. // * ****************************************************************************** *
  273.  
  274. // Thanks to Dair Grant (dair.grant@ucl.ac.uk) - I now check the MBarHeight
  275. //   of the *Front* process, and remember (via globals) when executing in bkgd.
  276.  
  277. // Remember that this function must be called from within that app's context!
  278. Boolean TestScreenSaver() {
  279.     static short attempts = 0;
  280.     Boolean inFront, wantToBlock;
  281.     long result;
  282.     ProcessSerialNumber frontPSN, curPSN;
  283.  
  284.     inFront = wantToBlock = false;
  285.  
  286.     // Most screensavers should register themselves this way
  287.     if (!Gestalt('SAVR', &result) && (result & 0x02)) wantToBlock = true;
  288.       else {
  289.         // We also want to hide ourselves if the foreground application
  290.         // has hidden the menu bar, since this implies they're taking
  291.         // over the whole screen (and they probably don't want us visible).
  292.         
  293.         // Only when we are executing in the foreground app can we check the
  294.         //   height of the menubar. When the front process has hidden its
  295.         //   menubar, then we set a global flag to enact our desires.
  296.         if (!GetFrontProcess(&frontPSN) && !GetCurrentProcess(&curPSN))
  297.             if (SameProcess(&frontPSN, &curPSN, &inFront)) inFront = false;
  298.         
  299.         if (inFront && (GetMBarHeight() == 0)) wantToBlock = true;
  300.         }
  301.  
  302.     // Unlike previous versions, we now wait 3 times before showing or
  303.     //    hiding the windows. This reduces flicker when games hide the 
  304.     //    menubar shortly, and doesn't hide the window during PopUpMenuSelect().
  305.     //    Thanks to Ammon Skidkmore (ammon@cs.byu.edu)
  306.     if (wantToBlock == glob.blockFloats) attempts = 0;
  307.       else if (++attempts >= 3) {
  308.         glob.blockFloats = wantToBlock;
  309.         attempts = 0;
  310.         }
  311.     
  312.     return(glob.blockFloats);
  313.     }
  314.  
  315.